package com.wx.lambda.ii.chapter5;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * 第5章测试
 * (1) 找出2011年发生的所有交易，并按交易额排序（从低到高）。
 * (2) 交易员都在哪些不同的城市工作过？
 * (3) 查找所有来自于剑桥的交易员，并按姓名排序。
 * (4) 返回所有交易员的姓名字符串，按字母顺序排序。
 * (5) 有没有交易员是在米兰工作的？
 * (6) 打印生活在剑桥的交易员的所有交易额。
 * (7) 所有交易中，最高的交易额是多少？
 * (8) 找到交易额最小的交易。
 */
@Slf4j
public class Chapter5Test2 {

    public static final String CAMBRIDGE = "Cambridge";

    public static void main(String[] args) {
        Trader raoul = new Trader("Raoul", CAMBRIDGE);
        Trader mario = new Trader("Mario", "Milan");
        Trader alan = new Trader("Alan", CAMBRIDGE);
        Trader brian = new Trader("Brian", CAMBRIDGE);
        List<Transaction> transactions = Arrays.asList(
                new Transaction(brian, 2011, 300),
                new Transaction(raoul, 2012, 1000),
                new Transaction(raoul, 2011, 400),
                new Transaction(mario, 2012, 710),
                new Transaction(mario, 2012, 700),
                new Transaction(alan, 2012, 950)
        );

        /*
            找出2011年发生的所有交易，并按交易额排序（从低到高）
         */
        transactions.stream()
                .filter(t -> t.getYear() == 2011)
                .sorted(Comparator.comparing(Transaction::getValue))
                .forEach(t -> log.info(t.toString()));
        /*
            交易员都在哪些不同的城市工作过？
         */
        transactions.stream()
                .map(Transaction::getTrader)
                .map(Trader::getCity)
                .distinct()
                .forEach(log::info);

        /*
            查找所有来自于剑桥的交易员，并按姓名排序。
         */
        transactions.stream()
                .map(Transaction::getTrader)
                .filter(t -> t.getCity().equals(CAMBRIDGE))
                .sorted(Comparator.comparing(Trader::getName))
                .forEach(t->log.info(t.toString()));
        /*
            返回所有交易员的姓名字符串，按字母顺序排序。
         */
        transactions.stream()
                .map(Transaction::getTrader)
                .map(Trader::getName)
                .distinct()
                .sorted(Comparator.naturalOrder())
                .forEach(log::info);
        /*
            有没有交易员是在米兰工作的？
         */
        String workPlace = "Milan";
        log.info("有没有交易员是在 {} 工作的，结果是：{}",
                workPlace , transactions.stream().anyMatch(t -> t.getTrader().getCity().equals(workPlace)) ? "有":"没有");

        transactions.stream()
                .filter(t -> t.getTrader().getCity().equals(CAMBRIDGE))
                .map(Transaction::getValue)
                .reduce(Integer::sum)
                .map(String::valueOf)
                .ifPresent(log::info);
        /*
        所有交易中，最高的交易额是多少？
         */
        transactions.stream()
                .max(Comparator.comparing(Transaction::getValue))
                .map(Transaction::getValue)
                .map(String::valueOf)
                .ifPresent(log::info);
        /*
         * 找到交易额最小的交易。
         */
        transactions.stream()
                .min(Comparator.comparing(Transaction::getValue))
                .map(Transaction::getValue)
                .map(String::valueOf)
                .ifPresent(log::info);

        /*
            勾股定理 a * a + b * b = c * c
         */

        IntStream.rangeClosed(1, 100)
                .boxed()
                .flatMap(i -> IntStream.rangeClosed(1, 100)
                        .boxed()
                        .filter(j -> Math.sqrt((double)i * (double)i  + (double)j * (double)j) % 1 == 0) // 过滤浮点型
                        .map(j -> new double[]{i, j, Math.sqrt(i * i + j * j)}))
                .forEach(a -> log.info(a[0]+","+a[1]+","+a[2]));

        /*
         * 斐波纳契数列的一部分：0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55
         * (0, 1), (1, 1), (1, 2), (2, 3), (3, 5), (5, 8), (8, 13), (13, 21)
         * iterate方法生成斐波纳契元组序列中的前20个元素
         */
        Stream.iterate(new int[]{0,1}, n -> new int[]{n[1],n[0]+n[1]})
                 .limit(20)
                .forEach(a -> log.info("({},{})",a[0],a[1]));

    }


}

@Data
class Trader {
    private final String name;
    private final String city;
}

@Data
class Transaction {
    private final Trader trader;
    private final int year;
    private final int value;
}